package me.qi.kancha.configuration;

import com.google.gson.JsonDeserializer;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializer;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import me.qi.kancha.dto.enums.base.BaseEnum;
import lombok.SneakyThrows;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.lang.reflect.Method;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 *
 *
 * @author sun
 * @date 2022/1/5 11:58
 * @modified By：
 */
public class GsonTypeAdapter {

    /**
     * String类型Json处理器，null输出为""，"",空格等读取为null
     */
    public static final TypeAdapter stringTypeAdapter = new TypeAdapter<String>() {
        @Override
        public void write(JsonWriter writer, String value) throws IOException {
            if (value == null) {
                writer.value("");
                return;
            }
            writer.value(value);
        }

        @Override
        public String read(JsonReader reader) throws IOException {
            if (reader.peek() == JsonToken.NULL) {
                reader.nextNull();
                return null;
            }
            String value = reader.nextString().trim();
            if (ObjectUtils.isEmpty(value)) {
                return null;
            }
            return value;
        }
    };

    /**
     * oauth2 异常
     */
    public static final TypeAdapter oauthExceptionAdapter = new TypeAdapter<OAuth2Exception>() {

        @Override
        public void write(JsonWriter jsonWriter, OAuth2Exception e) throws IOException {
            jsonWriter.beginObject();
            jsonWriter.name(OAuth2Exception.ERROR).value(e.getOAuth2ErrorCode());
            jsonWriter.name(OAuth2Exception.DESCRIPTION).value(e.getMessage());
            jsonWriter.endObject();
        }
        @Override
        public OAuth2Exception read(JsonReader jsonReader) {
            return null;
        }
    };

    /**
     * 通用枚举
     */
    public static class EnumAdapter extends TypeAdapter<BaseEnum> {

        private Class rawType;

        public EnumAdapter(Class rawType) {
            this.rawType = rawType;
        }

        @Override
        public void write(JsonWriter jsonWriter, BaseEnum baseEnum) throws IOException {
            if (baseEnum == null) {
                jsonWriter.nullValue();
            } else {
                Enum e = (Enum) baseEnum;
                jsonWriter.value(e.name() + ":" + baseEnum.getDesc());
            }
        }

        @SneakyThrows
        @Override
        public BaseEnum read(JsonReader jsonReader) throws IOException {
            if (jsonReader.peek() == JsonToken.NULL) {
                jsonReader.nextNull();
                return null;
            }
            String name = jsonReader.nextString();
            if (ObjectUtils.isEmpty(name)) {
                return null;
            }
            Method method = rawType.getMethod("valueOf", String.class);
            Object obj = method.invoke(null, name);
            return (BaseEnum) obj;
        }
    }

    /**
     * 日期 LocalDate - 序列化
     */
    public static final JsonSerializer<LocalDate> dateSerializer = (localDate, type, jsonSerializationContext) ->
            new JsonPrimitive(localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
    /**
     * 日期 LocalDate - 反序列化
     */
    public static final JsonDeserializer<LocalDate> dateDeserializer = (src, typeOfT, context) ->
            LocalDate.parse(src.getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));

    /**
     * 时间 LocalDateTime - 序列化
     */
    public static final JsonSerializer<LocalDateTime> dateTimeSerializer = (localDateTime, type, jsonSerializationContext) ->
            new JsonPrimitive(localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

    /**
     * 日期 LocalDateTime - 反序列化
     */
    public static final JsonDeserializer<LocalDateTime> dateTimeDeserializer = (src, typeOfT, context) ->
            LocalDateTime.parse(src.getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

}
